﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Odyssey.Controls
{
    /// <summary>
    /// Bases class for PageAnimations
    /// </summary>
    public abstract class PageAnimation : DependencyObject
    {
        private Duration duration = new Duration(TimeSpan.FromMilliseconds(300d));
        private Storyboard storyboard;

        /// <summary>
        /// Gets or sets the page uri where to navigate from or to which triggers this PageAnimation.
        /// If this value is left empty, this PageAnimation triggers for all transitions if no other explicit PageAnimation is available.
        /// </summary>
        public Uri Page { get; set; }

        /// <summary>
        /// Gets or sets the internal storyboard.
        /// </summary>
        protected Storyboard InternalStoryboard
        {
            get { return storyboard ?? (storyboard = CreateStoryboard()); }
            set
            {
                if (storyboard != null) storyboard.Completed -= OnStoryboardCompleted;
                storyboard = value;
                if (storyboard != null) storyboard.Completed += OnStoryboardCompleted;
            }
        }

        /// <summary>
        /// Gets or sets the duration for the animation. The default value is 300 milliseconds.
        /// </summary>
        public Duration Duration
        {
            get { return duration; }
            set { duration = value; }
        }

        /// <summary>
        /// Gets or sets the PageTransitionMode which triggers this PageTransition.
        /// </summary>
        public PageAnimationMode Mode { get; set; }

        /// <summary>
        /// Shows the specified page.
        /// </summary>
        /// <param name="page">Page to show.</param>
        /// <returns>True if an animation is in progress, otherwise false.</returns>
        public bool Show(Page page)
        {
            return ShowOverride(page);
        }

        /// <summary>
        /// Shows the specified page.
        /// </summary>
        /// <param name="page">Page to hide.</param>
        /// <returns>True if an animation is in progress, otherwise false.</returns>
        public bool Hide(Page page)
        {
            return HideOverride(page);
        }

        /// <summary>
        /// implements the animation when the specified page gets visible.
        /// </summary>
        protected abstract bool ShowOverride(Page page);

        /// <summary>
        /// implements the animation when the specified page gets hidden.
        /// </summary>
        /// <param name="page"></param>
        protected abstract bool HideOverride(Page page);

        protected void OnCompleted()
        {
            if (Completed != null) Completed(this, EventArgs.Empty);
        }

        /// <summary>
        /// Creates a new storyboard which fires OnCompleted when completed.
        /// </summary>
        private Storyboard CreateStoryboard()
        {
            Storyboard sb = new Storyboard();
            sb.Completed += new EventHandler(OnStoryboardCompleted);
            storyboard = sb;
            return sb;
        }

        private void OnStoryboardCompleted(object sender, EventArgs e)
        {
            OnCompleted();
        }

        public virtual void OnNavigated(Page page)
        {
            if (storyboard != null)
            {
                storyboard.Stop();
                storyboard.SeekAlignedToLastTick(TimeSpan.MinValue);
                storyboard = null;
            }
        }

        protected Storyboard GetClearStoryboard()
        {
            Storyboard sb = InternalStoryboard;
            sb.Stop();
            storyboard.SeekAlignedToLastTick(TimeSpan.MinValue);
            sb.Children.Clear();
            return sb;
        }


        public event EventHandler Completed;
    }
}
